home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pycentral-data / pyversions.py < prev    next >
Text File  |  2009-10-11  |  17KB  |  435 lines

  1. #! /usr/bin/python
  2.  
  3. import os, re, string, sys
  4. try:
  5.     SetType = set
  6. except NameError:
  7.     import sets
  8.     SetType = sets.Set
  9.     set = sets.Set
  10.  
  11. class PyCentralEmptyValueError(ValueError):
  12.     """Python Central Value Error"""
  13.     pass
  14.  
  15. _defaults = None
  16. def read_default(name=None):
  17.     global _defaults
  18.     from ConfigParser import SafeConfigParser, NoOptionError
  19.     if not _defaults:
  20.         if os.path.exists('/usr/share/python/debian_defaults'):
  21.             config = SafeConfigParser()
  22.             config.readfp(file('/usr/share/python/debian_defaults'))
  23.             _defaults = config
  24.         else:
  25.             raise ValueError
  26.     if _defaults and name:
  27.         try:
  28.             value = _defaults.get('DEFAULT', name)
  29.         except NoOptionError:
  30.             raise ValueError
  31.         return value
  32.     return None
  33.  
  34. def parse_versions(vstring, add_exact=False):
  35.     # Fix packages which were built with the broken dh_pycentral 0.5.50ubuntu1.
  36.     if vstring.lower().startswith("python:versions="):
  37.         vstring = string.split(vstring, "=", maxsplit=1)[1]
  38.     import operator
  39.     operators = { None: operator.eq, '=': operator.eq,
  40.                   '>=': operator.ge, '<=': operator.le,
  41.                   '<<': operator.lt
  42.                   }
  43.     vinfo = {}
  44.     exact_versions = set([])
  45.     version_range = set(supported_versions(version_only=True)
  46.                         + old_versions(version_only=True))
  47.     relop_seen = False
  48.     for field in vstring.split(','):
  49.         field = field.strip()
  50.         if field == 'all':
  51.             vinfo['all'] = 'all'
  52.             continue
  53.         if field in ('current', 'current_ext'):
  54.             vinfo['current'] = field
  55.             continue
  56.         vinfo.setdefault('versions', set())
  57.         ve = re.compile('(>=|<=|<<|=)? *(\d\.\d)$')
  58.         m = ve.match(field)
  59.         try:
  60.             op, v = m.group(1), m.group(2)
  61.             if op in (None, '='):
  62.                 exact_versions.add(v)
  63.             else:
  64.                 relop_seen = True
  65.                 filtop = operators[op]
  66.                 version_range = [av for av in version_range if filtop(av ,v)]
  67.         except Exception:
  68.             raise ValueError, 'error parsing Python-Version attribute'
  69.     if add_exact:
  70.         if exact_versions:
  71.             vinfo['vexact'] = exact_versions
  72.         if 'versions' in vinfo:
  73.             if relop_seen:
  74.                 vinfo['versions'] = set(version_range)
  75.             else:
  76.                 del vinfo['versions']
  77.     else:
  78.         if 'versions' in vinfo:
  79.             vinfo['versions'] = exact_versions
  80.             if relop_seen:
  81.                 vinfo['versions'] = exact_versions.union(version_range)
  82.     return vinfo
  83.  
  84. _old_versions = None
  85. def old_versions(version_only=False):
  86.     global _old_versions
  87.     if not _old_versions:
  88.         try:
  89.             value = read_default('old-versions')
  90.             _old_versions = [s.strip() for s in value.split(',')]
  91.         except ValueError:
  92.             _old_versions = []
  93.     if version_only:
  94.         return [v[6:] for v in _old_versions]
  95.     else:
  96.         return _old_versions
  97.  
  98. _unsupported_versions = None
  99. def unsupported_versions(version_only=False):
  100.     global _unsupported_versions
  101.     if not _unsupported_versions:
  102.         try:
  103.             value = read_default('unsupported-versions')
  104.             _unsupported_versions = [s.strip() for s in value.split(',')]
  105.         except ValueError:
  106.             _unsupported_versions = []
  107.     if version_only:
  108.         return [v[6:] for v in _unsupported_versions]
  109.     else:
  110.         return _unsupported_versions
  111.  
  112. _supported_versions = None
  113. def supported_versions(version_only=False):
  114.     global _supported_versions
  115.     if not _supported_versions:
  116.         try:
  117.             value = read_default('supported-versions')
  118.             _supported_versions = [s.strip() for s in value.split(',')]
  119.         except ValueError:
  120.             cmd = ['/usr/bin/apt-cache', '--no-all-versions',
  121.                    'show', 'python-all']
  122.             try:
  123.                 import subprocess
  124.                 p = subprocess.Popen(cmd, bufsize=1,
  125.                                      shell=False, stdout=subprocess.PIPE)
  126.                 fd = p.stdout
  127.             except ImportError:
  128.                 fd = os.popen(' '.join(cmd))
  129.             depends = None
  130.             for line in fd:
  131.                 if line.startswith('Depends:'):
  132.                     depends = line.split(':', 1)[1].strip().split(',')
  133.             fd.close()
  134.             if depends:
  135.                 depends = [re.sub(r'\s*(\S+)[ (]?.*', r'\1', s) for s in depends]
  136.                 _supported_versions = depends
  137.             if not _supported_versions:
  138.                 # last resort: python-minimal not installed, apt-cache
  139.                 # not available, hard code the value, #394084
  140.                 _supported_versions = ['python2.4', 'python2.5']
  141.     if version_only:
  142.         return [v[6:] for v in _supported_versions]
  143.     else:
  144.         return _supported_versions
  145.  
  146. _default_version = None
  147. def default_version(version_only=False):
  148.     global _default_version
  149.     if not _default_version:
  150.         try:
  151.             _default_version = link = os.readlink('/usr/bin/python')
  152.         except OSError:
  153.             _default_version = None
  154.             try:
  155.                 cmd = ['/usr/bin/python', '-c', 'import sys; print sys.version[:3]']
  156.                 import subprocess
  157.                 p = subprocess.Popen(cmd, bufsize=1,
  158.                                      shell=False, stdout=subprocess.PIPE)
  159.                 fd = p.stdout
  160.             except ImportError:
  161.                 fd = os.popen("/usr/bin/python -c 'import sys; print sys.version[:3]'")
  162.             line = fd.readline().strip()
  163.             fd.close()
  164.             if re.match(r'\d\.\d$', line):
  165.                 _default_version = 'python' + line
  166.         # consistency check
  167.         try:
  168.             debian_default = read_default('default-version')
  169.         except ValueError:
  170.             debian_default = "python2.5"
  171.         if not _default_version in (debian_default, os.path.join('/usr/bin', debian_default)):
  172.             raise ValueError, "/usr/bin/python does not match the python default version. It must be reset to point to %s" % debian_default
  173.         _default_version = debian_default
  174.     if version_only:
  175.         return _default_version[6:]
  176.     else:
  177.         return _default_version
  178.  
  179. def requested_versions(vstring, version_only=False):
  180.     versions = None
  181.     vinfo = parse_versions(vstring, add_exact=True)
  182.     supported = supported_versions(version_only=True)
  183.     if len(vinfo) == 1:
  184.         if 'all' in vinfo:
  185.             versions = supported
  186.         elif 'current' in vinfo:
  187.             versions = [default_version(version_only=True)]
  188.         elif 'vexact' in vinfo:
  189.             versions = vinfo['vexact']
  190.         else:
  191.             versions = vinfo['versions'].intersection(supported)
  192.     elif 'all' in vinfo and 'current' in vinfo:
  193.         raise ValueError, "both `current' and `all' in version string"
  194.     elif 'all' in vinfo:
  195.         if 'versions' in vinfo:
  196.             versions = vinfo['versions'].intersection(supported)
  197.         else:
  198.             versions = set(supported)
  199.         if 'vexact' in vinfo:
  200.             versions.update(vinfo['vexact'])
  201.     elif 'current' in vinfo:
  202.         current = default_version(version_only=True)
  203.         if not current in vinfo['versions']:
  204.             raise ValueError, "`current' version not in supported versions"
  205.         versions = [current]
  206.     elif 'versions' in vinfo or 'vexact' in vinfo:
  207.         versions = set()
  208.         if 'versions' in vinfo:
  209.             versions = vinfo['versions'].intersection(supported)
  210.         if 'vexact' in vinfo:
  211.             versions.update(vinfo['vexact'])
  212.     else:
  213.         raise ValueError, 'error in version string'
  214.     if not versions:
  215.         raise PyCentralEmptyValueError, 'empty set of versions'
  216.     if version_only:
  217.         return versions
  218.     else:
  219.         return ['python%s' % v for v in versions]
  220.  
  221. # This function is used by python-central to decide which installed
  222. # runtimes must be supported. It's not nice, but it's designed to mimic
  223. # closely requested_versions in an attempt to avoid introducing bugs this
  224. # late in the release cycle. Some cleanup is in order post-etch though.
  225. def requested_versions_for_runtime(vstring, version_only=False):
  226.     versions = None
  227.     vinfo = parse_versions(vstring, add_exact=True)
  228.     old = old_versions(version_only=True)
  229.     unsupported = unsupported_versions(version_only=True)
  230.     supported = supported_versions(version_only=True)
  231.     # You might want to add unsupported versions too... later.
  232.     supported.extend(old)
  233.     if len(vinfo) == 1:
  234.         if 'all' in vinfo:
  235.             versions = supported
  236.         elif 'current' in vinfo:
  237.             versions = [default_version(version_only=True)]
  238.         elif 'vexact' in vinfo:
  239.             versions = vinfo['vexact']
  240.         else:
  241.             versions = vinfo['versions'].intersection(supported)
  242.     elif 'all' in vinfo and 'current' in vinfo:
  243.         raise ValueError, "both `current' and `all' in version string"
  244.     elif 'all' in vinfo:
  245.         if 'versions' in vinfo:
  246.             versions = vinfo['versions'].intersection(supported)
  247.         else:
  248.             versions = set(supported)
  249.         if 'vexact' in vinfo:
  250.             versions.update(vinfo['vexact'])
  251.     elif 'current' in vinfo:
  252.         current = default_version(version_only=True)
  253.         if not current in vinfo['versions']:
  254.             raise ValueError, "`current' version not in supported versions"
  255.         versions = [current]
  256.     elif 'versions' in vinfo or 'vexact' in vinfo:
  257.         versions = set()
  258.         if 'versions' in vinfo:
  259.             versions = vinfo['versions'].intersection(supported)
  260.         if 'vexact' in vinfo:
  261.             versions.update(vinfo['vexact'])
  262.     else:
  263.         raise ValueError, 'error in version string'
  264.     if not versions:
  265.         raise PyCentralEmptyValueError, 'empty set of versions'
  266.     if version_only:
  267.         return versions
  268.     else:
  269.         return ['python%s' % v for v in versions]
  270.  
  271. def installed_versions(version_only=False):
  272.     import glob
  273.     supported = supported_versions()
  274.     versions = [os.path.basename(s)
  275.                 for s in glob.glob('/usr/bin/python[0-9].[0-9]')
  276.                 if os.path.basename(s) in supported]
  277.     versions.sort()
  278.     if version_only:
  279.         return [v[6:] for v in versions]
  280.     else:
  281.         return versions
  282.  
  283. class ControlFileValueError(ValueError):
  284.     pass
  285. class MissingVersionValueError(ValueError):
  286.     pass
  287.  
  288. def extract_pyversion_attribute(fn, pkg):
  289.     """read the debian/control file, extract the XS-Python-Version
  290.     field; check that XB-Python-Version exists for the package."""
  291.  
  292.     version = None
  293.     sversion = None
  294.     section = None
  295.     for line in file(fn):
  296.         line = line.strip()
  297.         if line == '':
  298.             if section == None:
  299.                 continue
  300.             if pkg == 'Source':
  301.                 break
  302.             section = None
  303.         elif line.startswith('Source:'):
  304.             section = 'Source'
  305.         elif line.startswith('Package: ' + pkg):
  306.             section = pkg
  307.         elif line.startswith('XS-Python-Version:'):
  308.             if section != 'Source':
  309.                 raise ValueError, \
  310.                       'attribute XS-Python-Version not in Source section'
  311.             sversion = line.split(':', 1)[1].strip()
  312.         elif line.startswith('XB-Python-Version:'):
  313.             if section == pkg:
  314.                 version = line.split(':', 1)[1].strip()
  315.     if section == None:
  316.         raise ControlFileValueError, 'not a control file'
  317.     if pkg == 'Source':
  318.         if sversion == None:
  319.             raise MissingVersionValueError, \
  320.                   'missing XS-Python-Version in control file'
  321.         return sversion
  322.     if version == None:
  323.         raise MissingVersionValueError, \
  324.               'missing XB-Python-Version for package `%s' % pkg
  325.     return version
  326.  
  327. # compatibility functions to parse debian/pyversions
  328.  
  329. def version_cmp(ver1,ver2):
  330.     v1=[int(i) for i in ver1.split('.')]
  331.     v2=[int(i) for i in ver2.split('.')]
  332.     return cmp(v1,v2)
  333.  
  334. def requested_versions_bis(vstring, version_only=False):
  335.     versions = []
  336.     py_supported_short = supported_versions(version_only=True)
  337.     for item in vstring.split(','):
  338.         v=item.split('-')
  339.         if len(v)>1:
  340.             if not v[0]:
  341.                 v[0] = py_supported_short[0]
  342.             if not v[1]:
  343.                 v[1] = py_supported_short[-1]
  344.             for ver in py_supported_short:
  345.                 try:
  346.                     if version_cmp(ver,v[0]) >= 0 \
  347.                            and version_cmp(ver,v[1]) <= 0:
  348.                         versions.append(ver)
  349.                 except ValueError:
  350.                     pass
  351.         else:
  352.             if v[0] in py_supported_short:
  353.                 versions.append(v[0])
  354.     versions.sort(version_cmp)
  355.     if not versions:
  356.         raise ValueError, 'empty set of versions'
  357.     if not version_only:
  358.         versions=['python'+i for i in versions]
  359.     return versions
  360.  
  361. def extract_pyversion_attribute_bis(fn):
  362.     vstring = file(fn).readline().rstrip('\n')
  363.     return vstring
  364.  
  365. def main():
  366.     from optparse import OptionParser
  367.     usage = '[-v] [-h] [-d|--default] [-s|--supported] [-i|--installed] [-r|--requested <version string>|<control file>]'
  368.     parser = OptionParser(usage=usage)
  369.     parser.add_option('-d', '--default',
  370.                       help='print the default python version',
  371.                       action='store_true', dest='default')
  372.     parser.add_option('-s', '--supported',
  373.                       help='print the supported python versions',
  374.                       action='store_true', dest='supported')
  375.     parser.add_option('-r', '--requested',
  376.                       help='print the python versions requested by a build; the argument is either the name of a control file or the value of the XS-Python-Version attribute',
  377.                       action='store_true', dest='requested')
  378.     parser.add_option('-i', '--installed',
  379.                       help='print the installed supported python versions',
  380.                       action='store_true', dest='installed')
  381.     parser.add_option('-v', '--version',
  382.                       help='print just the version number(s)',
  383.                       default=False, action='store_true', dest='version_only')
  384.     opts, args = parser.parse_args()
  385.     program = os.path.basename(sys.argv[0])
  386.  
  387.     if opts.default and len(args) == 0:
  388.         try:
  389.             print default_version(opts.version_only)
  390.         except ValueError, msg:
  391.             print "%s:" % program, msg
  392.             sys.exit(1)
  393.     elif opts.supported and len(args) == 0:
  394.         print ' '.join(supported_versions(opts.version_only))
  395.     elif opts.installed and len(args) == 0:
  396.         print ' '.join(installed_versions(opts.version_only))
  397.     elif opts.requested and len(args) <= 1:
  398.         if len(args) == 0:
  399.             versions = 'debian/control'
  400.         else:
  401.             versions = args[0]
  402.         try:
  403.             if os.path.isfile(versions):
  404.                 fn = versions
  405.                 try:
  406.                     vstring = extract_pyversion_attribute(fn, 'Source')
  407.                     vs = requested_versions(vstring, opts.version_only)
  408.                 except ControlFileValueError:
  409.                     sys.stderr.write("%s: not a control file: %s, " \
  410.                                      % (program, fn))
  411.                     sys.exit(1)
  412.                 except MissingVersionValueError:
  413.                     fn = os.path.join(os.path.dirname(fn), 'pyversions')
  414.                     sys.stderr.write("%s: missing XS-Python-Version in control file, fall back to %s\n" \
  415.                                      % (program, fn))
  416.                     try:
  417.                         vstring = extract_pyversion_attribute_bis(fn)
  418.                         vs = requested_versions_bis(vstring, opts.version_only)
  419.                     except IOError:
  420.                         sys.stderr.write("%s: missing debian/pyversions file, fall back to supported versions\n" \
  421.                                          % program)
  422.                         vs = supported_versions(opts.version_only)
  423.             else:
  424.                 vs = requested_versions(versions, opts.version_only)
  425.             print ' '.join(vs)
  426.         except ValueError, msg:
  427.             sys.stderr.write("%s: %s\n" % (program, msg))
  428.             sys.exit(1)
  429.     else:
  430.         sys.stderr.write("usage: %s %s\n" % (program, usage))
  431.         sys.exit(1)
  432.  
  433. if __name__ == '__main__':
  434.     main()
  435.